package org.cybzacg.encryption.model;

import org.cybzacg.encryption.enums.EncryptionStatus;
import org.cybzacg.encryption.enums.EncryptionAlgorithm;
import org.cybzacg.encryption.context.EncryptionContext;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.HashMap;
import java.util.Objects;

/**
 * 加密结果类
 * 封装加密操作的结果信息
 * 
 * @author encryption team
 * @version 1.0
 */
public class EncryptionResult {
    
    private final EncryptionStatus status;
    private final byte[] data;
    private final EncryptionAlgorithm algorithm;
    private final String messageId;
    private final LocalDateTime timestamp;
    private final long processingTime;
    private final String errorMessage;
    private final Exception exception;
    private final Map<String, Object> metadata;
    private final EncryptionContext context;
    
    private EncryptionResult(Builder builder) {
        this.status = builder.status;
        this.data = builder.data;
        this.algorithm = builder.algorithm;
        this.messageId = builder.messageId;
        this.timestamp = builder.timestamp;
        this.processingTime = builder.processingTime;
        this.errorMessage = builder.errorMessage;
        this.exception = builder.exception;
        this.metadata = new HashMap<>(builder.metadata);
        this.context = builder.context;
    }
    
    /**
     * 获取状态
     * 
     * @return 状态
     */
    public EncryptionStatus getStatus() {
        return status;
    }
    
    /**
     * 获取结果数据
     * 
     * @return 结果数据，可能为null
     */
    public byte[] getData() {
        return data != null ? data.clone() : null;
    }
    
    /**
     * 获取使用的算法
     * 
     * @return 算法
     */
    public EncryptionAlgorithm getAlgorithm() {
        return algorithm;
    }
    
    /**
     * 获取消息ID
     * 
     * @return 消息ID
     */
    public String getMessageId() {
        return messageId;
    }
    
    /**
     * 获取时间戳
     * 
     * @return 时间戳
     */
    public LocalDateTime getTimestamp() {
        return timestamp;
    }
    
    /**
     * 获取处理时间（毫秒）
     * 
     * @return 处理时间
     */
    public long getProcessingTime() {
        return processingTime;
    }
    
    /**
     * 获取错误消息
     * 
     * @return 错误消息，可能为null
     */
    public String getErrorMessage() {
        return errorMessage;
    }
    
    /**
     * 获取异常信息
     * 
     * @return 异常信息，可能为null
     */
    public Exception getException() {
        return exception;
    }
    
    /**
     * 获取元数据
     * 
     * @return 元数据映射的副本
     */
    public Map<String, Object> getMetadata() {
        return new HashMap<>(metadata);
    }
    
    /**
     * 获取上下文
     * 
     * @return 上下文
     */
    public EncryptionContext getContext() {
        return context;
    }
    
    /**
     * 检查是否成功
     * 
     * @return 是否成功
     */
    public boolean isSuccess() {
        return status.isSuccess();
    }
    
    /**
     * 检查是否失败
     * 
     * @return 是否失败
     */
    public boolean isFailure() {
        return status.isFailure();
    }
    
    /**
     * 获取数据长度
     * 
     * @return 数据长度
     */
    public int getDataLength() {
        return data != null ? data.length : 0;
    }
    
    /**
     * 获取元数据值
     * 
     * @param key 键
     * @return 值，可能为null
     */
    public Object getMetadata(String key) {
        return metadata.get(key);
    }
    
    /**
     * 创建成功的加密结果
     * 
     * @param data 加密数据
     * @param algorithm 使用的算法
     * @param context 上下文
     * @return 加密结果
     */
    public static EncryptionResult success(byte[] data, EncryptionAlgorithm algorithm, EncryptionContext context) {
        return new Builder()
                .status(EncryptionStatus.SUCCESS)
                .data(data)
                .algorithm(algorithm)
                .context(context)
                .build();
    }
    
    /**
     * 创建失败的加密结果
     * 
     * @param status 状态
     * @param errorMessage 错误消息
     * @param context 上下文
     * @return 加密结果
     */
    public static EncryptionResult failure(EncryptionStatus status, String errorMessage, EncryptionContext context) {
        return new Builder()
                .status(status)
                .errorMessage(errorMessage)
                .context(context)
                .build();
    }
    
    /**
     * 创建异常的加密结果
     * 
     * @param exception 异常
     * @param context 上下文
     * @return 加密结果
     */
    public static EncryptionResult error(Exception exception, EncryptionContext context) {
        return new Builder()
                .status(EncryptionStatus.UNKNOWN_ERROR)
                .exception(exception)
                .errorMessage(exception.getMessage())
                .context(context)
                .build();
    }
    
    /**
     * 建造者类
     */
    public static class Builder {
        private EncryptionStatus status = EncryptionStatus.SUCCESS;
        private byte[] data;
        private EncryptionAlgorithm algorithm;
        private String messageId;
        private LocalDateTime timestamp = LocalDateTime.now();
        private long processingTime;
        private String errorMessage;
        private Exception exception;
        private Map<String, Object> metadata = new HashMap<>();
        private EncryptionContext context;
        
        public Builder status(EncryptionStatus status) {
            this.status = status;
            return this;
        }
        
        public Builder data(byte[] data) {
            this.data = data;
            return this;
        }
        
        public Builder algorithm(EncryptionAlgorithm algorithm) {
            this.algorithm = algorithm;
            return this;
        }
        
        public Builder messageId(String messageId) {
            this.messageId = messageId;
            return this;
        }
        
        public Builder timestamp(LocalDateTime timestamp) {
            this.timestamp = timestamp;
            return this;
        }
        
        public Builder processingTime(long processingTime) {
            this.processingTime = processingTime;
            return this;
        }
        
        public Builder errorMessage(String errorMessage) {
            this.errorMessage = errorMessage;
            return this;
        }
        
        public Builder exception(Exception exception) {
            this.exception = exception;
            return this;
        }
        
        public Builder metadata(String key, Object value) {
            this.metadata.put(key, value);
            return this;
        }
        
        public Builder metadata(Map<String, Object> metadata) {
            this.metadata = new HashMap<>(metadata);
            return this;
        }
        
        public Builder context(EncryptionContext context) {
            this.context = context;
            return this;
        }
        
        public EncryptionResult build() {
            return new EncryptionResult(this);
        }
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        EncryptionResult that = (EncryptionResult) o;
        return processingTime == that.processingTime &&
                status == that.status &&
                Objects.equals(messageId, that.messageId) &&
                Objects.equals(timestamp, that.timestamp) &&
                Objects.equals(errorMessage, that.errorMessage) &&
                Objects.equals(metadata, that.metadata);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(status, messageId, timestamp, processingTime, errorMessage, metadata);
    }
    
    @Override
    public String toString() {
        return "EncryptionResult{" +
                "status=" + status +
                ", algorithm=" + algorithm +
                ", messageId='" + messageId + '\'' +
                ", timestamp=" + timestamp +
                ", processingTime=" + processingTime +
                ", dataLength=" + getDataLength() +
                ", errorMessage='" + errorMessage + '\'' +
                '}';
    }
}
